//-------------------------------------------------------------------
//	Copyright (c) 2010-2012 Zhirnov Andrey
//	This file is part of the "UXGEN" project.
//	See copyright notice in "Engine.h".
//-------------------------------------------------------------------

#include "Builtin.h"
#include "../../Utils/CRenderQueue.h"
#include "../../CRender.h"
#include "../../../../Resources/AllResources.h"

namespace Engine
{
namespace RenderUtils
{

//------------------- CDRBuiltinDrawRenderQueue ---------------------//
/*
=================================================
	
=================================================
*/
	CDRBuiltinDrawRenderQueue::CDRBuiltinDrawRenderQueue(IRTPass *pParent):
		IRTPass(pParent), _pQueue(nullptr), _pIteration(nullptr)
	{
	}
		
/*
=================================================
	
=================================================
*/
	CDRBuiltinDrawRenderQueue::~CDRBuiltinDrawRenderQueue()
	{
	}
	
/*
=================================================
	
=================================================
*/
	bool CDRBuiltinDrawRenderQueue::Create(uint uLayer)
	{
		TRTMessage	s_msg;
		s_msg.GetCameraRQ();

		CHECK_RETURN( _pParent->ProcessMessage( s_msg ) );

		_pQueue	 = s_msg.sData.pCameraRQ;

		if ( uLayer == -1 )
		{
			s_msg.GetIteration();
			CHECK_RETURN( _pParent->ProcessMessage( s_msg ) );
			
			_pIteration = s_msg.sData.pIVec4;

			CHECK_VALUE( _pIteration->x <= e_render_layer::_LAST_LAYER &&
						 _pIteration->y <= e_render_layer::_LAST_LAYER );
			
			_pProc		= & _s_DrawIterationLayers;
		}
		else
		{
			CHECK_VALUE( uLayer <= e_render_layer::_LAST_LAYER );

			_uLayer = uLayer;
			_pProc	= & _s_DrawLayer;
		}

		return true;
	}
		
/*
=================================================
	
=================================================
*/
	bool CDRBuiltinDrawRenderQueue::ProcessMessage(TRTMessage &sMsg)
	{
		if ( --sMsg.iDepth <= 0 )
			return false;

		if ( sMsg.eType == TRTMessage::GET_PASS && sMsg.sData.sPass.eType == GetPassType() )
		{
			sMsg.sData.sPass.pPass = this;
			return true;
		}

		if ( sMsg.eType == TRTMessage::GET_LIGHT_AND_SHADOW_SETUP )
		{
			sMsg.sData.sPasses.pLast = this;
		}

		return _pParent->ProcessMessage( sMsg );
	}
	
/*
=================================================
	
=================================================
*/
	void CDRBuiltinDrawRenderQueue::_s_DrawLayer(void *pThis)
	{
		CDRBuiltinDrawRenderQueue		 *	p_this		= (CDRBuiltinDrawRenderQueue *)pThis;
		array< TRenderObject > const &	a_objects	= (*p_this->_pQueue)->RenderObjects()[ p_this->_uLayer ];

		for (usize i = 0; i < a_objects.Count(); ++i)
		{
			a_objects[i].Draw();
		}
	}
	
/*
=================================================
	
=================================================
*/
	void CDRBuiltinDrawRenderQueue::_s_DrawIterationLayers(void *pThis)
	{
		CDRBuiltinDrawRenderQueue		 *	p_this		= (CDRBuiltinDrawRenderQueue *)pThis;
		array< TRenderObject > const &	a_objects	= (*p_this->_pQueue)->RenderObjects()[ p_this->_pIteration->w ];

		for (usize i = 0; i < a_objects.Count(); ++i)
		{
			a_objects[i].Draw();
		}
	}




//------------------ CBuiltinDrawRenderQueueOC --------------------//
/*
=================================================
	
=================================================
*/
	CBuiltinDrawRenderQueueOC::CBuiltinDrawRenderQueueOC(IRTPass *pParent):
		CDRBuiltinDrawRenderQueue( pParent ),	_uVPMatLoc(-1), _uAABBLoc(-1), _pQuery(nullptr)
	{
	}
	
/*
=================================================
	
=================================================
*/
	CBuiltinDrawRenderQueueOC::~CBuiltinDrawRenderQueueOC()
	{
	}
	
/*
=================================================
	
=================================================
*/
	bool CBuiltinDrawRenderQueueOC::Create(const CShaderProgramPtr &pShader, uint uLayer)
	{
		CHECK_ARGUMENT( pShader != nullptr );

		CHECK_RETURN( CDRBuiltinDrawRenderQueue::Create( uLayer ) );
		
		TRTMessage	s_msg;
		s_msg.GetQuery( gl_query::ANY_SAMPLES_PASSED );

		CHECK_RETURN( _pParent->ProcessMessage( s_msg ) );

		_pQuery	 = s_msg.sData.sQuery.pQuery;
		_pShader = pShader;

		_uVPMatLoc = pShader->GetUniform( "unVPMat" );
		_uAABBLoc  = pShader->GetUniform( "unAABB" );

		CHECK_VALUE( _uVPMatLoc != uint8(-1) && _uAABBLoc != uint8(-1) );

		if ( _pProc == & _s_DrawIterationLayers )
			_pProc = & _s_DrawIterationLayersOC;
		else
			_pProc = & _s_DrawLayerOC;

		return true;
	}
		
/*
=================================================
	
=================================================
*/
	bool CBuiltinDrawRenderQueueOC::ProcessMessage(TRTMessage &sMsg)
	{
		if ( --sMsg.iDepth <= 0 )
			return false;

		if ( sMsg.eType == TRTMessage::GET_PASS && sMsg.sData.sPass.eType == GetPassType() )
		{
			sMsg.sData.sPass.pPass = this;
			return true;
		}

		if ( sMsg.eType == TRTMessage::GET_LIGHT_AND_SHADOW_SETUP )
		{
			sMsg.sData.sPasses.pLast = this;
		}

		return _pParent->ProcessMessage( sMsg );
	}
	
/*
=================================================
	
=================================================
*/
	void CBuiltinDrawRenderQueueOC::_s_DrawLayerOC(void *pThis)
	{
		CBuiltinDrawRenderQueueOC	 *	p_this		= (CBuiltinDrawRenderQueueOC *)pThis;
		array< TRenderObject > const &	a_objects	= (*p_this->_pQueue)->RenderObjects()[ p_this->_uLayer ];
		

		p_this->_pShader->Bind();
		glUniformMatrix4fv( p_this->_uVPMatLoc, 1, GL_FALSE, (const float *)GLOBAL::MSTACK()->GetMatrixVP().ptr() );


		for (usize i = 0; i < a_objects.Count(); ++i)
		{
			// occlusion culling
			p_this->_pQuery->Begin( gl_query::ANY_SAMPLES_PASSED );

			p_this->_pShader->Bind();
			glUniform3fv( p_this->_uAABBLoc, 2, (const float *)a_objects[i].sBBox.ptr() );
			
			bool				b_depth_mask = GLOBAL::SMAN()->GetDepthMask();
			e_color_mask::type	e_color_mask = GLOBAL::SMAN()->GetColorMask();

			GLOBAL::SMAN()->DepthMask( false );
			GLOBAL::SMAN()->ColorMask( false, false, false, false );

			GLOBAL::RENDERGL()->DrawPoint();

			p_this->_pQuery->End();

			
			// conditional render
			GLOBAL::SMAN()->DepthMask( b_depth_mask );
			GLOBAL::SMAN()->ColorMask(	EnumCmp( e_color_mask, e_color_mask::R ),
										EnumCmp( e_color_mask, e_color_mask::G ),
										EnumCmp( e_color_mask, e_color_mask::B ),
										EnumCmp( e_color_mask, e_color_mask::A ) );

			p_this->_pQuery->BeginConditionalRender( gl_cond_render::QUERY_WAIT );

			a_objects[i].Draw();

			p_this->_pQuery->EngConditionalRender();
		}
	}
	
/*
=================================================
	
=================================================
*/
	void CBuiltinDrawRenderQueueOC::_s_DrawIterationLayersOC(void *pThis)
	{
		CBuiltinDrawRenderQueueOC	 *	p_this		= (CBuiltinDrawRenderQueueOC *)pThis;
		array< TRenderObject > const &	a_objects	= (*p_this->_pQueue)->RenderObjects()[ p_this->_pIteration->w ];

		
		p_this->_pShader->Bind();
		glUniformMatrix4fv( p_this->_uVPMatLoc, 1, GL_FALSE, (const float *)GLOBAL::MSTACK()->GetMatrix(e_transform::PROJECTION).ptr() );


		for (usize i = 0; i < a_objects.Count(); ++i)
		{
			// occlusion culling
			p_this->_pQuery->Begin( gl_query::ANY_SAMPLES_PASSED );

			p_this->_pShader->Bind();

			aabb_f	s_bbox	 = a_objects[i].sBBox;
			vec3	v_center = s_bbox.Center();

			s_bbox.SetBBox( vec3(0.f), s_bbox.Extent() );
			s_bbox *= GLOBAL::MSTACK()->GetMatrix(e_transform::VIEW);
			s_bbox.SetBBox( v_center + s_bbox.Center(), s_bbox.Extent() );

			glUniform3fv( p_this->_uAABBLoc, 2, (const float *)s_bbox.ptr() );
			
			bool				b_depth_mask = GLOBAL::SMAN()->GetDepthMask();
			e_color_mask::type	e_color_mask = GLOBAL::SMAN()->GetColorMask();

			GLOBAL::SMAN()->DepthMask( false );
			GLOBAL::SMAN()->ColorMask( false, false, false, false );

			GLOBAL::RENDERGL()->DrawPoint();

			p_this->_pQuery->End();


			// conditional render
			GLOBAL::SMAN()->DepthMask( b_depth_mask );
			GLOBAL::SMAN()->ColorMask(	EnumCmp( e_color_mask, e_color_mask::R ),
										EnumCmp( e_color_mask, e_color_mask::G ),
										EnumCmp( e_color_mask, e_color_mask::B ),
										EnumCmp( e_color_mask, e_color_mask::A ) );
			
			p_this->_pQuery->BeginConditionalRender( gl_cond_render::QUERY_BY_REGION_WAIT );

			a_objects[i].Draw();

			p_this->_pQuery->EngConditionalRender();
		}
	}
	
	/*
//---------------------- CBuiltinSetupShadow ----------------------//
		CBuiltinSetupShadow(IRTPass *pParent);
		~CBuiltinSetupShadow();

		bool Create(IRTPass *, e_light::type, e_shadow::type, const vec2 &);
		
		virtual bool ProcessMessage(TRTMessage &sMsg);


		
//---------------------- CBuiltinSetupLight -----------------------//
		CBuiltinSetupLight(IRTPass *pParent);
		~CBuiltinSetupLight();

		bool Create(const CBaseProgramShellPtr &, e_light::type, e_shadow::type);

		virtual bool ProcessMessage(TRTMessage &sMsg);


		
//---------------------- CBuiltinDrawLights -----------------------//
		CBuiltinDrawLights(IRTPass *pParent);
		~CBuiltinDrawLights();

		bool Create(IRTPass *, const CTexturePtr &, e_light::type);

		virtual bool ProcessMessage(TRTMessage &sMsg);
*/


//----------------------- CBuiltinSetCamera -----------------------//
/*
=================================================
	
=================================================
*/
	CBuiltinSetCamera::CBuiltinSetCamera(IRTPass *pParent):
		IRTPass(pParent), _pCameras(nullptr), _pIteration(nullptr), _pCurrentCameraRQ(nullptr)
	{
	}
	
/*
=================================================
	
=================================================
*/
	CBuiltinSetCamera::~CBuiltinSetCamera()
	{
	}
	
/*
=================================================
	
=================================================
*/
	bool CBuiltinSetCamera::Create(e_camera::type eCamType, uint uIndex)
	{
		TRTMessage	s_msg;
		s_msg.GetCameras( eCamType );

		CHECK_RETURN( _pParent->ProcessMessage( s_msg ) );

		_pCameras = s_msg.sData.sCameras.pCameras;
		_pCurrentCameraRQ = nullptr;

		if ( uIndex == -1 )
		{
			s_msg.GetIteration();
			CHECK_RETURN( _pParent->ProcessMessage( s_msg ) );

			_pIteration = s_msg.sData.pIVec4;
			_pProc		= & _s_SetIteration;
		}
		else
		{
			_uIndex = uIndex;
			_pProc	= & _s_SetIndex;
		}
		return true;
	}
	
/*
=================================================
	
=================================================
*/
	bool CBuiltinSetCamera::ProcessMessage(TRTMessage &sMsg)
	{
		if ( --sMsg.iDepth <= 0 )
			return false;

		if ( sMsg.eType == TRTMessage::GET_PASS && sMsg.sData.sPass.eType == GetPassType() )
		{
			sMsg.sData.sPass.pPass = this;
			return true;
		}

		if ( sMsg.eType == TRTMessage::GET_CURRENT_RENDER_QUEUE )
		{
			sMsg.sData.pCameraRQ = &_pCurrentCameraRQ;
			return true;
		}

		if ( sMsg.eType == TRTMessage::GET_LIGHT_AND_SHADOW_SETUP )
		{
			sMsg.sData.sPasses.pLast = this;
		}

		return _pParent->ProcessMessage( sMsg );
	}
	
/*
=================================================
	
=================================================
*/
	void CBuiltinSetCamera::_s_SetIteration(void *pThis)
	{
		CBuiltinSetCamera *	p_this	 = (CBuiltinSetCamera *)pThis;

		CHECK_VALUE_R( p_this->_pIteration->w < (isize)p_this->_pCameras->Count(), );

		p_this->_pCurrentCameraRQ	 = (*p_this->_pCameras)[ p_this->_pIteration->w ];

		ICameraObject	*	p_camera = p_this->_pCurrentCameraRQ->Camera();
		CViewport		*	p_view	 = p_camera->GetViewport();

		p_view->Bind();		// set mvp matrices
		GLOBAL::RENDER()->SetViewport( p_view );
	}
	
/*
=================================================
	
=================================================
*/
	void CBuiltinSetCamera::_s_SetIndex(void *pThis)
	{
		CBuiltinSetCamera *	p_this	 = (CBuiltinSetCamera *)pThis;

		CHECK_VALUE_R( p_this->_uIndex < p_this->_pCameras->Count(), );
		
		p_this->_pCurrentCameraRQ	 = (*p_this->_pCameras)[ p_this->_uIndex ];

		ICameraObject	*	p_camera = p_this->_pCurrentCameraRQ->Camera();
		CViewport		*	p_view	 = p_camera->GetViewport();

		p_view->Bind();		// set vp matrices
		GLOBAL::RENDER()->SetViewport( p_view );
	}



//-------------------- CBuiltinUseUserPostProcess -----------------//
/*
=================================================
	
=================================================
*/
	CBuiltinUseUserPostProcess::CBuiltinUseUserPostProcess(IRTPass *pParent):
		IRTPass(pParent), _pPostProcess(nullptr), _uIndex(0)
	{
	}
	
/*
=================================================
	
=================================================
*/
	CBuiltinUseUserPostProcess::~CBuiltinUseUserPostProcess()
	{
	}
		
/*
=================================================
	
=================================================
*/
	bool CBuiltinUseUserPostProcess::Create(uint uIndex)
	{
		TRTMessage	s_msg;
		s_msg.GetUserPostProcess();

		CHECK_RETURN( _pParent->ProcessMessage( s_msg ) );
		
		_pPostProcess	= s_msg.sData.pPostProcess;
		_uIndex			= uIndex;
		_pProc			= & _s_UsePostProcess;

		if ( (*_pPostProcess) != nullptr )
			CHECK_VALUE( uIndex < (*_pPostProcess)->GetMaxIndex() );

		return true;
	}
	
/*
=================================================
	
=================================================
*/
	bool CBuiltinUseUserPostProcess::ProcessMessage(TRTMessage &sMsg)
	{
		if ( --sMsg.iDepth <= 0 )
			return false;

		if ( sMsg.eType == TRTMessage::GET_PASS && sMsg.sData.sPass.eType == GetPassType() )
		{
			sMsg.sData.sPass.pPass = this;
			return true;
		}

		if ( sMsg.eType == TRTMessage::GET_LIGHT_AND_SHADOW_SETUP )
		{
			sMsg.sData.sPasses.pLast = this;
		}

		return _pParent->ProcessMessage( sMsg );
	}
	
/*
=================================================
	
=================================================
*/
	void CBuiltinUseUserPostProcess::_s_UsePostProcess(void *pThis)
	{
		CBuiltinUseUserPostProcess *	p_this = (CBuiltinUseUserPostProcess *)pThis;

		CHECK_VALUE_R( (*p_this->_pPostProcess) != nullptr, );
		CHECK_RETURN_R( (*p_this->_pPostProcess)->Process( p_this->_uIndex, true ), );
	}



//-------------------- CBuiltinDrawFullscreenQuad -----------------//
/*
=================================================
	
=================================================
*/
	CBuiltinDrawFullscreenQuad::CBuiltinDrawFullscreenQuad(IRTPass *pParent):
		IRTPass(pParent), _pProgram(), _bFlipY(false)
	{
	}
	
/*
=================================================
	
=================================================
*/
	CBuiltinDrawFullscreenQuad::~CBuiltinDrawFullscreenQuad()
	{
	}
		
/*
=================================================
	
=================================================
*/
	bool CBuiltinDrawFullscreenQuad::Create(const CBaseProgramShellPtr &pProgram, bool bFlipY)
	{
		CHECK_ARGUMENT( pProgram != nullptr && pProgram->IsValid() );

		_pProgram = pProgram;
		_pProc    = & _s_Draw;
		_bFlipY	  = bFlipY;

		return true;
	}
	
/*
=================================================
	
=================================================
*/
	bool CBuiltinDrawFullscreenQuad::ProcessMessage(TRTMessage &sMsg)
	{
		if ( --sMsg.iDepth <= 0 )
			return false;

		if ( sMsg.eType == TRTMessage::GET_PASS && sMsg.sData.sPass.eType == GetPassType() )
		{
			sMsg.sData.sPass.pPass = this;
			return true;
		}

		if ( sMsg.eType == TRTMessage::GET_LIGHT_AND_SHADOW_SETUP )
		{
			sMsg.sData.sPasses.pLast = this;
		}

		return _pParent->ProcessMessage( sMsg );
	}
	
/*
=================================================
	
=================================================
*/
	void CBuiltinDrawFullscreenQuad::_s_Draw(void *pThis)
	{
		CBuiltinDrawFullscreenQuad *	p_this	= (CBuiltinDrawFullscreenQuad *)pThis;

		GLOBAL::MSTACK()->PushMatricesMVP();
		
		GLOBAL::RENDERGL()->Mode2D( p_this->_bFlipY );
		
		p_this->_pProgram->Bind();
		GLOBAL::RENDERGL()->DrawFSQuad();

		GLOBAL::MSTACK()->PopMatricesMVP();
	}



//--------------------- CBuiltinProfilerBegin ---------------------//
/*
=================================================
	
=================================================
*/
	CBuiltinProfilerBegin::CBuiltinProfilerBegin(IRTPass *pParent):
		IRTPass(pParent), _uIndex(-1)
	{
	}
	
/*
=================================================
	
=================================================
*/
	CBuiltinProfilerBegin::~CBuiltinProfilerBegin()
	{
	}
	
/*
=================================================
	
=================================================
*/
	bool CBuiltinProfilerBegin::Create(const char *pName)
	{
		_sName	 = pName;
		_pProc	 = & _s_Begin;

		return !_sName.Empty();
	}
	
/*
=================================================
	
=================================================
*/
	bool CBuiltinProfilerBegin::ProcessMessage(TRTMessage &sMsg)
	{
		if ( --sMsg.iDepth <= 0 )
			return false;

		if ( sMsg.eType == TRTMessage::GET_PASS && sMsg.sData.sPass.eType == GetPassType() )
		{
			sMsg.sData.sPass.pPass = this;
			return true;
		}

		if ( sMsg.eType == TRTMessage::GET_PROFILER_INDEX && *sMsg.sData.sProfiler.pName == _sName )
		{
			sMsg.sData.sProfiler.pIndex = &_uIndex;
			return true;
		}

		if ( sMsg.eType == TRTMessage::GET_LIGHT_AND_SHADOW_SETUP )
		{
			sMsg.sData.sPasses.pLast = this;
		}

		return _pParent->ProcessMessage( sMsg );
	}
	
/*
=================================================
	
=================================================
*/
	void CBuiltinProfilerBegin::_s_Begin(void *pThis)
	{
		CBuiltinProfilerBegin *	p_this = (CBuiltinProfilerBegin *)pThis;

		p_this->_uIndex = GLOBAL::RENDER()->GetProfiler()->BeginProfiling( p_this->_sName );
	}




//---------------------- CBuiltinProfilerEnd ----------------------//
/*
=================================================
	
=================================================
*/
	CBuiltinProfilerEnd::CBuiltinProfilerEnd(IRTPass *pParent):
		IRTPass(pParent), _pIndex(nullptr)
	{
	}
	
/*
=================================================
	
=================================================
*/
	CBuiltinProfilerEnd::~CBuiltinProfilerEnd()
	{
	}
	
/*
=================================================
	
=================================================
*/
	bool CBuiltinProfilerEnd::Create(const string &sName)
	{
		CHECK_ARGUMENT( !sName.Empty() );

		TRTMessage	s_msg;
		s_msg.GetProfilerIndex( sName );

		CHECK_RETURN( _pParent->ProcessMessage( s_msg ) );

		_pIndex		= s_msg.sData.sProfiler.pIndex;
		_pProc		= & _s_End;

		return true;
	}
		
/*
=================================================
	
=================================================
*/
	bool CBuiltinProfilerEnd::ProcessMessage(TRTMessage &sMsg)
	{
		if ( --sMsg.iDepth <= 0 )
			return false;

		if ( sMsg.eType == TRTMessage::GET_PASS && sMsg.sData.sPass.eType == GetPassType() )
		{
			sMsg.sData.sPass.pPass = this;
			return true;
		}

		if ( sMsg.eType == TRTMessage::GET_LIGHT_AND_SHADOW_SETUP )
		{
			sMsg.sData.sPasses.pLast = this;
		}

		return _pParent->ProcessMessage( sMsg );
	}
	
/*
=================================================
	
=================================================
*/
	void CBuiltinProfilerEnd::_s_End(void *pThis)
	{
		CBuiltinProfilerEnd *	p_this = (CBuiltinProfilerEnd *)pThis;

		GLOBAL::RENDER()->GetProfiler()->EndProfiling( *p_this->_pIndex );
	}



//------------------------ CBuiltinClearBuffer --------------------//
/*
=================================================
	
=================================================
*/
	CBuiltinClearBuffer::CBuiltinClearBuffer(IRTPass *pParent):
		IRTPass(pParent), _uIndex(0)
	{
	}
	
/*
=================================================
	
=================================================
*/
	CBuiltinClearBuffer::~CBuiltinClearBuffer()
	{
	}
	
/*
=================================================
	
=================================================
*/
	bool CBuiltinClearBuffer::Create(const color4f &sColor, e_fbo_attach::type eBuffer)
	{
		CHECK_ARGUMENT( eBuffer >= e_fbo_attach::COLOR_0 && eBuffer <= e_fbo_attach::COLOR_7 );	// 8 draw buffers

		memcpy( _aColor, sColor.ptr(), sizeof(_aColor) );
		_uIndex  = eBuffer - e_fbo_attach::COLOR_0;
		_pProc   = & _s_ClearColor;

		return true;
	}
	
/*
=================================================
	
=================================================
*/
	bool CBuiltinClearBuffer::Create(const float fValue, e_fbo_attach::type eBuffer)
	{
		CHECK_ARGUMENT( eBuffer == e_fbo_attach::DEPTH );

		_fDepth  = fValue;
		_uIndex  = 0;
		_pProc   = & _s_ClearDepth;

		return true;
	}
	
/*
=================================================
	
=================================================
*/
	bool CBuiltinClearBuffer::Create(const int iValue, e_fbo_attach::type eBuffer)
	{
		CHECK_ARGUMENT( eBuffer == e_fbo_attach::STENCIL || eBuffer == e_fbo_attach::_UNKNOWN || (
						eBuffer >= e_fbo_attach::COLOR_0 && eBuffer <= e_fbo_attach::COLOR_7 ) );

		if ( eBuffer == e_fbo_attach::_UNKNOWN )
		{
			_pProc	  = & _s_ClearAll;
		}
		else
		if ( eBuffer == e_fbo_attach::STENCIL )
		{
			_iStencil = iValue;
			_uIndex   = 0;
			_pProc    = & _s_ClearStencil;
		}
		else
		{
			color4f	s_color = Color::Convert<float>( *(const color4u *)&iValue );

			memcpy( _aColor, s_color.ptr(), sizeof(_aColor) );
			_uIndex  = eBuffer - e_fbo_attach::COLOR_0;
			_pProc   = & _s_ClearColor;
		}
		return true;
	}
		
/*
=================================================
	
=================================================
*/
	bool CBuiltinClearBuffer::ProcessMessage(TRTMessage &sMsg)
	{
		if ( --sMsg.iDepth <= 0 )
			return false;

		if ( sMsg.eType == TRTMessage::GET_PASS && sMsg.sData.sPass.eType == GetPassType() )
		{
			sMsg.sData.sPass.pPass = this;
			return true;
		}

		if ( sMsg.eType == TRTMessage::GET_LIGHT_AND_SHADOW_SETUP )
		{
			sMsg.sData.sPasses.pLast = this;
		}

		return _pParent->ProcessMessage( sMsg );
	}
	
/*
=================================================
	
=================================================
*/
	void CBuiltinClearBuffer::_s_ClearColor(void *pThis)
	{
		CBuiltinClearBuffer *	p_this = (CBuiltinClearBuffer *)pThis;

		GLOBAL::RENDERGL()->ClearColor( color4f( p_this->_aColor ), p_this->_uIndex );
	}
	
/*
=================================================
	
=================================================
*/
	void CBuiltinClearBuffer::_s_ClearDepth(void *pThis)
	{
		CBuiltinClearBuffer *	p_this = (CBuiltinClearBuffer *)pThis;
		
		GLOBAL::RENDERGL()->ClearDepth( p_this->_fDepth );
	}
	
/*
=================================================
	
=================================================
*/
	void CBuiltinClearBuffer::_s_ClearStencil(void *pThis)
	{
		CBuiltinClearBuffer *	p_this = (CBuiltinClearBuffer *)pThis;
		
		GLOBAL::RENDERGL()->ClearStencil( p_this->_iStencil );
	}
	
/*
=================================================
	
=================================================
*/
	void CBuiltinClearBuffer::_s_ClearAll(void *pThis)
	{
		GL_CALL( glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ) );
	}

//-------------------------------------------------------------------

}	// RenderUtils
}	// Engine